home *** CD-ROM | disk | FTP | other *** search
/ Mac Format 1995 June / MacFormat 25.iso / Shareware City / Developers / fortran-to-c-translator-11 / Mac F2C 1.1 / Mac F2C Documentation / When Mac F2C code won't run… < prev   
Text File  |  1995-01-13  |  6KB  |  172 lines

  1.     **************************************
  2.     **************************************
  3.  
  4.         WHEN Mac F2C CODE WON'T RUN…
  5.  
  6.     **************************************
  7.     **************************************
  8.  
  9.  
  10.  
  11. It is not uncommon for code produced by Mac F2C to compile without any 
  12. problems, but crash and burn badly when run.  In fact, if you get to the 
  13. ccommand() dialog (the one that asks you to set up standard input and 
  14. standard output), but crash immediately there after, it is almost certain 
  15. that you are blowing out the stack space.  The problem and its solution are 
  16. described below.
  17.  
  18. The problem arises because FORTRAN allocates memory for all its variables 
  19. statically.  The C code produced by Mac F2C by default uses automatic 
  20. storage for most variables.  On the Macintosh automatic variables get 
  21. stored on the stack.  When the FORTRAN code declares large arrays (quite 
  22. common in FORTRAN code), these become large arrays on the stack in the C 
  23. version.  Because less than 24K is normally allocated as stack space by 
  24. default on the Macintosh, your program blows out the stack.
  25.  
  26. The quick fix to try is to translate the FORTRAN code with the "Make local 
  27. variables automatic vice static whenever possible" option in the "C options 
  28. Options" dialog UNCHECKED.  This will move all of the large arrays from the 
  29. stack to the global data space.  You should also increase the memory 
  30. partition for your program (either in the Finder's "Get Info…" dialog if it 
  31. is a free-standing application, or in the appropriate THINK/CodeWarrior 
  32. dialog if it is under development) to allow for the extra memory required 
  33. by the large global arrays.
  34.  
  35. This "fix" will often solve the problem.  However, because THINK still 
  36. imposes a 32K limit on the amount of global data per file, you can still 
  37. have problems with files that have too many large arrays in them.  If you 
  38. are lucky, you can divide the file somehow so that the arrays are split 
  39. among several files and now don't violate the 32K/file limit.  However, 
  40. that might not be possible if, for example, all the arrays appear within a 
  41. single subroutine.
  42.  
  43. In such a case, the only solution is to edit the C code so that it 
  44. allocates the memory dynamically.
  45.  
  46. Let's work an example.  Consider the following simple FORTRAN program:
  47.  
  48.     program example
  49.     
  50.     double precision d
  51.     dimension a(100,100), b(100,200,20)
  52.     dimension d(50,20,10)
  53.     
  54.     a(100,100) = 1.0
  55.     b(100,200,20) = 1.0
  56.     d(50,20,10) = 1.0d0
  57.     
  58.     stop
  59.     end
  60.  
  61.  
  62. Basically all it does is allocate three arrays.  Note that the arrays are 
  63. not that large by FORTRAN standards.  Using the factory default options, 
  64. this program translates into:
  65.  
  66. /* JUNK.f -- translated by f2c (version 19941113).
  67.    You must link the resulting object file with the libraries:
  68.     -lf2c -lm   (in that order)
  69. */
  70.  
  71. #include "f2c.h"
  72.  
  73. /* Main program */ MAIN__(void)
  74. {
  75.     /* Builtin functions */
  76.     /* Subroutine */ int s_stop(char *, ftnlen);
  77.  
  78.     /* Local variables */
  79.     real a[10000]   /* was [100][100] */, b[400000] /* was [100][200][20] 
  80.         */;
  81.     doublereal d[10000] /* was [50][20][10] */;
  82.  
  83.     a[9999] = 1.f;
  84.     b[399999] = 1.f;
  85.     d[9999] = 1.;
  86.     s_stop("", 0L);
  87.     return 0;
  88. } /* MAIN__ */
  89.  
  90. /* Main program alias */ int example_ () { MAIN__ (); return 0; }
  91.  
  92.  
  93. Note how in the C version 410,000 reals and 10,000 doublereals are 
  94. allocated on the stack -- that's over 1.5MB on the stack.  Your program 
  95. will crash the moment it enters the MAIN__() function.  If you tried using 
  96. static vice automatic variables you would have over 32K of global data in 
  97. one file and it wouldn't build under THINK C.  Multi-dimensional arrays can 
  98. be quite large even when their individual dimensions are small.  It's easy 
  99. to blow out the stack or the THINK C limit on global data per file with 
  100. even one or two arrays of three or more dimensions.  I've also seen 
  101. programs get into problems because they have *lots* of small arrays.
  102.  
  103. The solution is to replace the array variables with pointers and allocate 
  104. the memory for them using malloc() or any of it's cousins.  Because C 
  105. treats pointers and arrays similarly, the rest of the code works as is. 
  106.  
  107. Applying this technique to the example yields the following modified code:
  108.  
  109. /* JUNK.f -- translated by f2c (version 19941113).
  110.    You must link the resulting object file with the libraries:
  111.     -lf2c -lm   (in that order)
  112. */
  113.  
  114. #include "f2c.h"
  115.  
  116. #define NEW_CODE            /* <========  to make the changes clear */
  117.  
  118. #ifdef NEW_CODE
  119. #include <stdlib.h>         /* Get prototypes for malloc(), etc */
  120. #endif
  121.  
  122. /* Main program */ MAIN__(void)
  123. {
  124.     /* Builtin functions */
  125.     /* Subroutine */ int s_stop(char *, ftnlen);
  126.  
  127.     /* Local variables */
  128. #ifdef NEW_CODE 
  129.     real        *a, *b;         /* Pointers instead of arrays */
  130.     doublereal  *d;         
  131. #else
  132.     real a[10000]   /* was [100][100] */, b[400000] /* was [100][200][20] 
  133.         */;
  134.     doublereal d[10000] /* was [50][20][10] */;
  135. #endif
  136.  
  137.  
  138. #ifdef NEW_CODE                                 /* allocate the memory */
  139.     a = (real *) malloc( 10000*sizeof(real) );
  140.     b = (real *) malloc( 400000*sizeof(real) );
  141.     d = (doublereal *) malloc( 10000*sizeof(doublereal) );
  142.     /* Remember to check a, b, and d for NULL (e.g., out of memory) */
  143. #endif
  144.  
  145.     a[9999] = 1.f;
  146.     b[399999] = 1.f;
  147.     d[9999] = 1.;
  148.     
  149. #ifdef NEW_CODE
  150.     free( a );          /* Don't forget to free the memory */
  151.     free( b );
  152.     free( d );
  153. #endif
  154.  
  155.     s_stop("", 0L);
  156.     return 0;
  157. } /* MAIN__ */
  158.  
  159. /* Main program alias */ int example_ () { MAIN__ (); return 0; }
  160.  
  161.  
  162. This version of the program will work fine so long as there is enough heap 
  163. space to allocate the memory requested in the malloc() calls.  You can add 
  164. more heap space by simply increasing the partition size of the program 
  165. (either in the Finder's "Get Info…" dialog if it is a free-standing 
  166. application, or in the appropriate THINK/CodeWarrior dialog if it is under 
  167. development).
  168.  
  169. This version will also work if the variables a, b, and d had been 
  170. declared static vice automatic.
  171.  
  172.